home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / source / music4c.sit / Music4C Folder / Sources Folder / pass3.c < prev    next >
Text File  |  1990-09-09  |  14KB  |  656 lines

  1. /*
  2. * ⌐ Graeme Gerrard 1990
  3. * Faculty of Music, University of Melbourne
  4. * Parkville Victoria 3052 Australia.
  5. *
  6. * ARPANET: grae@murdu.ucs.unimelb.edu.au
  7. * telephone: (613) 344 4127, Fax: (613) 344 5346
  8. */
  9.  
  10.  
  11. #include    "Music4C.h"
  12. #include    <math.h>
  13. #include    <unix.h>
  14. #include    "Music4C_Prototype.h"
  15. #include    "ErrorAlert.h"
  16.  
  17. Boolean pass3(void);
  18. void init_funcs(void);
  19. void free_funcs(void);
  20.  
  21. void initl(void);
  22. void setup(void);
  23. void orch(void);
  24. void ter(void);
  25. void final(void);
  26.  
  27. void    fread_card(void);
  28. Boolean    play(void);
  29. void    ClosePass3Input(void);
  30. void    calcPeakAndSOR(void);
  31.  
  32.  
  33. void    insert(void);
  34. void    gen(int, double *);
  35. void    remove_instr(void);
  36.  
  37. Boolean    spend(void);
  38. void    report_sect_time(void);
  39. void    report_end_time(void);
  40. void    calcPeakAndSOR(void);
  41.  
  42. Boolean    samout(void);
  43. void    check_params(void);
  44. extern    Boolean    Mac_write3(float *, float);
  45. void    dump_samps(void);
  46. extern    void        tell_mem(void);
  47.  
  48.  
  49. float        *SampsPtr;
  50. static    long    start_time;        /* for counting elapsed time */
  51. static    long    end_time;
  52. static    long    sect_start_time;
  53. static    long    sect_end_time;
  54. static    int        sectnum;            /* section number */
  55. int        nrec;                        /* record count */
  56. double    tt;                            /* time from start of run */
  57. double    t;                            /* time from start of section */
  58. static    int        nseg[MAXCHANS];        /* samples out of range for segment */
  59. static    int        nsect[MAXCHANS];    /* samples out of range per section */
  60. static    int        ntot[MAXCHANS];        /* samps out of range for run */
  61. static    double    sect[MAXCHANS];        /* max amp per section*/
  62. static    double    seg[MAXCHANS];        /* max amplitude for segment */
  63. static    double    peak[MAXCHANS];        /* max amplitude for run */
  64. double    *p;                            /* parameter array */
  65. double    *out;                        /* storage for samples */
  66. int        wrote_rec;                    /* flag indicating a record has been written to disk */
  67.  
  68. int        opcode;                        /* opcode */
  69. int        npargs;                        /* number of parameter arguments */
  70. int        insno;
  71. int        instype;
  72. static    double    delay;                /* delay, in number of samples, to end of segment */
  73. int        loc;                        /* pointer to out array for basic channel */
  74. static    int        iloc;
  75. static    int        length;
  76. extern    Str255    p2tmp;
  77.  
  78. int        samps_file;                    /* fd for pass3 sample file */
  79. extern    OSErr    theErr;
  80. extern    Str255    theMess1, theMess2;
  81.  
  82. typedef    struct    Instr_info {
  83.     int    i_type;
  84.     int    i_index;
  85.     struct    Instr_info    *next;
  86. }    Instr_info;
  87. Instr_info        *i_list;        /* linked list to record instruments on/off */
  88.  
  89.  
  90. Boolean pass3()
  91. {
  92.     extern    double    srate;
  93.     extern    int    out3_flag;
  94.     extern    int    RunToPass3;
  95.     extern    int    max_ins_types;
  96.     extern    int    nchnls;
  97.     register     int     i;
  98.     extern    Str255    sfile;        /* name of sound file */
  99.     double    st;
  100. /* overall maximum and minimum amplitudes for use in resource file */
  101.     extern    float        MaxSample;
  102.     extern    float        MinSample;
  103.     extern        int            SFvRefNum;
  104.     extern    FILE    *p2out;
  105.     extern    char    aString1[MAXSTRING];
  106.     extern    char    aString2[MAXSTRING];
  107.  
  108.  
  109.  
  110.  
  111.     MaxSample = 0.0;
  112.     MinSample = 0.0;
  113.     start_time = TickCount();
  114.     
  115.     p = (double *)NewPtr(MAXPARAMS * sizeof(double));
  116.     if ( (theErr = MemError())  != noErr ){
  117.         PstringCopy((char *)theMess1, "\pError allocating parameter buffer memory in pass3");
  118.         OSError(theMess1, NIL, theErr);
  119.     }
  120.     out = (double *)NewPtr(SAMPBUFSZ * sizeof(double));
  121.     if ( (theErr = MemError())  != noErr ){
  122.         PstringCopy((char *)theMess1, "\pError allocating out buffer memory in pass3");
  123.         OSError(theMess1, NIL, theErr);
  124.     }
  125.     SampsPtr = (float *)NewPtr(SAMPBUFSZ * sizeof(float));
  126.     if ( (theErr = MemError())  != noErr ){
  127.         PstringCopy((char *)theMess1, "\pError allocating sample buffer memory in pass3");
  128.         OSError(theMess1, NIL, theErr);
  129.     }
  130.     
  131.  
  132.     rewind(p2out);
  133.     
  134.     init_funcs();
  135.     iloc = 0;
  136.     nrec = 0;
  137.     sectnum = 0;
  138.     initl();
  139.     
  140.     tell_mem();
  141.     
  142.     tt = 0.0;
  143.     for ( i = 0; i < MAXCHANS; i++ ) {
  144.         nsect[i] = 0;
  145.         nseg[i] = 0;
  146.         sect[i] = 0.0;
  147.         seg[i] = 0.0;
  148.         peak[i] = 0.0;
  149.     }
  150.     opcode = 0;
  151.  
  152.     if ( out3_flag) {
  153.         Report("\n");
  154.         Report("\n");
  155.         Report("Pass3 output\n");
  156.     }
  157.     do {
  158.         sect_start_time = TickCount();
  159.         sectnum++;
  160.         t = 0.0;
  161.         if ( out3_flag) {
  162.             sprintf((char *)theMess1, "Section %d\n", sectnum);
  163.             Report((char *)theMess1);
  164.         }
  165.         
  166.         do {
  167.             fread_card();
  168.             if ( opcode == IOP  || opcode == ENDOP )
  169.                 st = p[2];
  170.             else
  171.                 st = p[1];
  172.  
  173.             delay = srate * (st - t);
  174.             if ( delay >= 1.0 ) { /* play up to end of current segment */
  175.                 if ( !play() ) {
  176.                     DisposPtr((Ptr)SampsPtr);
  177.                     ClosePass3Input();
  178.                     free_funcs();
  179.                     return(FALSE);
  180.                 }
  181.                 tt += (st - t);
  182.                 if ( out3_flag) {
  183.                     sprintf((char *)theMess1, "t%10f ...%10f\ttt%10f", t, st, tt);
  184.                     Report((char *)theMess1);
  185.                 }
  186.                 for ( i = 0; i < nchnls; i++ ) {
  187.                     if ( out3_flag) {
  188.                         sprintf((char *)theMess1, "\t%10f", seg[i] );
  189.                         Report((char *)theMess1);
  190.                     }
  191.                     sect[i] = MAX(sect[i], seg[i]);
  192.                     seg[i] = 0.0;
  193.                 }
  194.                 if ( out3_flag)
  195.                     Report("\n");
  196.                 if ( (nseg[0] + nseg[1] + nseg[2] + nseg[3]) > 0 ) {
  197.                     if ( out3_flag)
  198.                         Report("No. of samples out of range\t\t\t\t");
  199.                     for ( i = 0; i < nchnls; i++ ) {
  200.                         if ( out3_flag) {
  201.                             sprintf((char *)theMess1, "\t%d", nseg[i]);
  202.                             Report((char *)theMess1);
  203.                         }
  204.                         nsect[i] += nseg[i];
  205.                         nseg[i] = 0;
  206.                     }
  207.                     if ( out3_flag)
  208.                         Report("\n");
  209.                 }
  210.             }
  211.             t = st;
  212.  
  213.             /*    tell_mem();*/
  214.             if ( opcode == IOP )
  215.                 insert();
  216.             else if ( opcode == FOP )
  217.                 gen(npargs, p);
  218.             else if ( opcode == ENDOP ) {
  219.                 remove_instr();
  220.                 ter();
  221.             }
  222.         } while ( opcode != SOP && opcode != EOP );
  223.         if (opcode == EOP) {
  224.  
  225.             if (!spend() ) {
  226.                 DisposPtr((Ptr)SampsPtr);
  227.                 free_funcs();
  228.                 return(FALSE);
  229.             }
  230.         }
  231.         report_sect_time();
  232.  
  233.     } while ( opcode != EOP );
  234.  
  235.     if (!spend() ) {
  236.         DisposPtr((Ptr)SampsPtr);
  237.         free_funcs();
  238.         return(FALSE);
  239.     }
  240.     report_end_time();
  241.     free_funcs();
  242.     ClosePass3Input();
  243.     DisposPtr((Ptr)SampsPtr);
  244.     final();
  245.     calcPeakAndSOR();
  246.     
  247.     return(TRUE);
  248. }
  249.  
  250.  
  251.  
  252. void    remove_instr()
  253. {
  254. /* delete instrument from queue, it has finished playing */
  255.     
  256.     Instr_info *cursor;
  257.     Instr_info *prev;
  258.     Instr_info *toDelete;
  259.  
  260.  
  261.     cursor = i_list;
  262.     prev = i_list;
  263.     instype = (int)p[0];
  264.      insno = (int)p[1];
  265.     
  266.     while ( cursor != NIL ) {
  267.         if ( cursor->i_type == instype && cursor->i_index == insno ) {
  268.             /* found the instr, delete it from list */
  269.             if ( cursor == i_list ) { /* list head */
  270.                 toDelete = i_list;
  271.                 if ( i_list->next )
  272.                     i_list = i_list->next;
  273.                 /* only 1 instrument ?*/
  274.                 else    
  275.                     i_list = NIL;
  276.                 DisposPtr((Ptr)toDelete);
  277.             }
  278.             else {
  279.                 toDelete = cursor;
  280.                 prev->next = cursor->next;
  281.                 DisposPtr((Ptr)toDelete);
  282.             }
  283.             break;
  284.         }
  285.         else {
  286.             prev = cursor;
  287.             cursor = cursor->next;
  288.         }
  289.     }
  290. }
  291.  
  292.  
  293.  
  294. void    insert()
  295. {
  296. /* enter the instrument in queue */
  297.  
  298.     extern    int max_ins_types;
  299.     Instr_info *cursor;
  300.     Instr_info *prev;
  301.     Instr_info *newInstr;
  302.     
  303.     cursor = i_list;
  304.     prev = i_list;
  305.     instype = (int)p[0];
  306.     insno = (int)p[1];
  307.     while ( cursor != NIL ) {
  308.         if ( cursor->i_type == instype && cursor->i_index == insno ) {
  309.             sprintf(aString1, "Instrument type %d, instrument %d, ",
  310.                 instype, insno);
  311.             sprintf(aString2, "at start time = %f", p[2]);
  312.             CtoPstr(aString2);
  313.             CtoPstr(aString1);
  314.             PstringCat((char *)theMess1, (char *)aString1);
  315.             PstringCat((char *)theMess1, (char *)aString2);
  316.             PstringCopy((char *)theMess2, "\pis already playing");
  317.             OSError(theMess1, theMess2, NIL);
  318.         }
  319.         prev = cursor;
  320.         cursor = cursor->next;
  321.     }
  322.  
  323.     newInstr = (Instr_info *)NewPtr(sizeof(Instr_info));
  324.     if ( (theErr = MemError())  != noErr ){
  325.         PstringCopy((char *)theMess1, "\pError allocating memory in insert");
  326.         OSError(theMess1, theMess2, NIL);
  327.     }
  328.     newInstr->next = NIL;
  329.     newInstr->i_type = instype;
  330.     newInstr->i_index = insno;
  331.     
  332.     if ( i_list == NIL)
  333.         i_list = newInstr;
  334.     else
  335.         prev->next = newInstr;
  336.     setup();
  337.  
  338.  
  339.     if ( instype > max_ins_types ) {
  340.         sprintf(aString1, "No such instrument type no. = %d", instype);
  341.         sprintf(aString2, " (start time %f)", p[2] );
  342.         CtoPstr(aString1);
  343.         CtoPstr(aString2);
  344.         PstringCopy((char *)theMess1, (char *)aString1);
  345.         PstringCopy((char *)theMess2, (char *)aString2);
  346.         OSError(theMess1, theMess2, NIL);
  347.     }
  348. }
  349.  
  350.  
  351. Boolean    play()
  352. {
  353.     extern    int    dump_samps_flag;
  354.     double    *sptr;
  355.     register int i;
  356.     register int j;
  357.     long nsamps;
  358.     extern    int    nchnls;
  359.     double    x;
  360.     Instr_info *cursor;
  361.     extern    double    rescalingConst;
  362.     cursor = i_list;
  363.     
  364.  
  365. /* determine number of samples in the next time segment */
  366.     nsamps = ((long) (delay + 0.5) ) * nchnls;
  367.     while ( nsamps > 0L ) {
  368.         nsamps -= SAMPBUFSZ;
  369.         if ( nsamps < 0L ) {
  370.             length = (int)nsamps + SAMPBUFSZ;
  371.             for ( i = 0, sptr = out; i < SAMPBUFSZ; i++ )
  372.                 *sptr++ = 0.0;
  373.         }
  374.         else {
  375.             length = SAMPBUFSZ;
  376.             sptr = out;
  377.             for ( i = 0; i < length; i++)
  378.                 *sptr++ = 0.0;
  379.         }
  380.  
  381.         if ( i_list != NIL ) {
  382.             for ( i = 0; i < length; i += nchnls ) {
  383.                 loc = i;
  384.                 cursor = i_list;
  385.                 while ( cursor != NIL ) {    
  386.                     instype = cursor->i_type;
  387.                     insno = cursor->i_index;
  388.                     orch();
  389.                     cursor = cursor->next;
  390.                 }
  391.             }
  392.             if ( rescalingConst > 0.0 ) {
  393.                 for ( i = 0, sptr = out; i < length; i++ )
  394.                     *sptr++ *= rescalingConst;
  395.             }
  396.             for ( i = 0; i < length; i += nchnls ) {
  397.                 for ( j = 0; j < nchnls; j++ ) {
  398.                     x = fabs(out[i+j]);
  399.                     if ( x > SAMPMAX )
  400.                         nseg[j]++;
  401.                     if ( x > seg[j] )
  402.                         seg[j] = x;
  403.                     if ( seg[j] > peak[j] )
  404.                         peak[j] = seg[j];
  405.                 }
  406.             }
  407.         }
  408.         wrote_rec = 0;
  409.         if (!samout() ) {
  410.             return(FALSE);
  411.         }
  412.         
  413.     }
  414.     return(TRUE);
  415. }
  416.  
  417. void    report_sect_time()
  418. {
  419.     register int i;
  420.     long secs;
  421.     int mins;
  422.     sect_end_time = TickCount();
  423.     secs = (long)(sect_end_time - sect_start_time) / 60L;
  424.     mins = secs / 60;
  425.     if ( mins > 0 ) {
  426.         if ( out3_flag ) {
  427.             sprintf((char *)theMess1, "End of section %d, synthesis time was %d mins %ld secs\n",
  428.                 sectnum, mins, secs - (mins * 60));
  429.             Report((char *)theMess1);
  430.         }
  431.     }
  432.     else {
  433.         if ( out3_flag ) {
  434.             sprintf((char *)theMess1, "End of section %d, synthesis time was %ld secs\n",
  435.                 sectnum, secs );
  436.             Report((char *)theMess1);
  437.         }
  438.     }
  439.     if ( out3_flag )
  440.         Report("Maximum amplitude per channel was\n");
  441.     for ( i = 0; i < nchnls; i++ ) {
  442.         if ( out3_flag ) {
  443.             sprintf( (char *)theMess1, "\t\t\t\t\t\tchannel %d\t%f\n", i+1, sect[i] );
  444.             Report((char *)theMess1);
  445.         }
  446.         peak[i] = MAX(peak[i], sect[i]);
  447.         sect[i] = 0.0;
  448.     }
  449.     if ( out3_flag )
  450.         Report("\n");
  451.     if ( (nsect[0] + nsect[1] + nsect[2] + nsect[3]) > 0 ) {
  452.         if ( out3_flag )
  453.             Report("No. of samples out of range\t\t\t\t");
  454.         for ( i = 0; i < nchnls; i++ ) {
  455.             if ( out3_flag ) {
  456.                 sprintf((char *)theMess1, "\t%d", nsect[i]);
  457.                 Report((char *)theMess1);
  458.             }
  459.             ntot[i] += nsect[i];
  460.             nsect[i] = 0;
  461.         }
  462.         if ( out3_flag )
  463.             Report("\n");
  464.     }
  465. }
  466.  
  467. void    report_end_time()
  468. {
  469.     long secs;
  470.     int mins;
  471.     end_time = TickCount();
  472.     secs = (long)(end_time - start_time) / 60L;
  473.     mins = secs / 60;
  474.     if ( mins > 0 ) {
  475.         if ( out3_flag ) {
  476.             Report("End of Pass3\n");
  477.             sprintf((char *)theMess1, "Total synthesis time was\t\t%d mins %ld secs\n", mins, secs - (mins * 60));
  478.             Report((char *)theMess1);
  479.         }
  480.     }
  481.     else {
  482.         if ( out3_flag ) {
  483.             Report("End of Pass3\n");
  484.             sprintf((char *)theMess1, "Total synthesis time was \t\t\t%ld secs\n", secs );
  485.             Report((char *)theMess1);
  486.         }
  487.     }
  488. }
  489.  
  490.  
  491. void    calcPeakAndSOR()
  492. {
  493.     register int i;
  494.  
  495.     double x = 0.0;
  496.     double r = 0.0;
  497.     for ( i = 0; i < nchnls; i++ )
  498.         x = MAX(x, peak[i]);
  499.     r = SAMPMAX / x;
  500.  
  501.     if ( out3_flag ) {
  502.         sprintf((char *)theMess1, "Overall peak amplitude was \t\t\t%f\n", x);
  503.         Report((char *)theMess1);
  504.         sprintf((char *)theMess1, "Rescaling constant\t\t\t\t\t%f\n", r );
  505.         Report((char *)theMess1);
  506.     }
  507.     if ( out3_flag ) {
  508.         if ( (ntot[0] + ntot[1] + ntot[2] + ntot[3]) > 0 ) {
  509.             Report("Sum of samples out of range\t\t\t\t");
  510.             for ( i = 0; i < nchnls; i++ ) {
  511.                 sprintf( (char *)theMess1, "\t%d", ntot[i]);
  512.                 Report((char *)theMess1);
  513.             }
  514.             Report("\n");
  515.         }
  516.     }
  517. }
  518.  
  519.  
  520. void    ClosePass3Input()
  521. {    
  522.     int i;
  523.     i = fclose(p2out);
  524.     i = remove((char *)p2tmp);    /* ??? */
  525. }
  526.  
  527.  
  528. void    fread_card()
  529. {
  530. /* read an event record from the pass3 input file. Remember,
  531. *   this has been sorted chronologically by pass2
  532. */
  533.     register int i;
  534.     register int k;
  535.     extern    FILE    *p2out;
  536.     i = fread(&opcode, sizeof(int), 1, p2out);
  537.     if ( opcode == SOP || opcode == EOP ) {
  538.         i = fread(p, sizeof(double), 1, p2out);
  539.         p[1] = p[0];
  540.     }
  541.     else if ( opcode == ENDOP ) {
  542.         i = fread(p, sizeof(double), 3, p2out);     /* get instype, insno, end time */
  543.     }
  544.     else if ( opcode == NULLOP ) {
  545.         npargs = 0;
  546.     }
  547.     else {
  548.         i = fread(&npargs, sizeof(int), 1, p2out);
  549.         k = fread(p, sizeof(double), npargs, p2out);
  550.     }
  551. }
  552.  
  553.  
  554. void    check_params()
  555. {
  556.     register int i;
  557.  
  558.     if ( out3_flag ) {
  559.         sprintf( (char *)theMess1, "opcode = %d\n", opcode );
  560.         Report((char *)theMess1);
  561.         for ( i = 0; i < npargs; i++ ) {
  562.             sprintf( (char *)theMess1, "\tp[%d] = %f\n", i, p[i]);
  563.             Report((char *)theMess1);
  564.         }
  565.     }
  566. }
  567.  
  568.  
  569. Boolean    spend()
  570. {
  571. /* clear remainder of last output record before writing it to file */
  572.     register int i;
  573.     register float    *sptr;
  574.     if (!wrote_rec) {
  575.         sptr = (SampsPtr + iloc);
  576.         for ( i = iloc; i < SAMPBUFSZ; i++ )
  577.             *sptr++ = 0.0;
  578.         if ( iloc < SAMPBUFSZ)
  579.             --sptr;
  580.         if (!Mac_write3(SampsPtr, tt)) {
  581.             return(FALSE);
  582.         }
  583.         return(TRUE);
  584.  
  585.     }
  586.     return(TRUE);
  587. }
  588.  
  589. Boolean    samout()
  590. {
  591. /* append the newly generated samples to the output buffer,
  592. * and call to write buffer to soundfile
  593. */
  594.  
  595.     extern    float        MaxSample;
  596.     extern    float        MinSample;
  597.     register     int        i;
  598.     double    *optr;
  599.     float        *sptr;
  600.     
  601.     optr = out;
  602.     sptr = (SampsPtr + iloc);
  603.     for ( i = 0; i < length; i++) {
  604.         *sptr = (float)*optr++;
  605.         if ( *sptr > MaxSample)
  606.             MaxSample = *sptr;
  607.             
  608.         if ( *sptr < MinSample )
  609.             MinSample = *sptr;
  610.         iloc++;
  611.             
  612.         if ( dump_samps_flag )
  613.             dump_samps();
  614.         if ( iloc == SAMPBUFSZ ) {
  615.             if (!Mac_write3(SampsPtr, tt)) {
  616.                 return(FALSE);
  617.             }
  618.             iloc = 0;
  619.             sptr = SampsPtr;
  620.         }
  621.         else
  622.             sptr++;
  623.     }
  624.     if ( iloc < SAMPBUFSZ)
  625.         --sptr;
  626.     return(TRUE);
  627. }
  628.  
  629.  
  630. /*
  631.  
  632. this from old unix version
  633. write3()
  634. {
  635.  
  636.     register int i;
  637.     unsigned    towrite = SAMPBUFSZ * sizeof(float);
  638.     
  639.     nrec++;
  640.     if ( CreateSoundFile ) {
  641.         if ( (i = write(samps_file, (char *)SampsPtr, towrite)) != towrite)
  642.             fprintf(stderr, "error writing sample buffer in write3, error %d\n", i);
  643.     }
  644.     fprintf(stderr, "write3, rec no%d\n", nrec);
  645.  
  646.     wrote_rec = 1;
  647.  
  648. }
  649.  */
  650. void    dump_samps()
  651. {
  652. }
  653.  
  654. /*----------------------------------------------------------------------------*/
  655.  
  656.